package com.hmall.gateway.filter;

import cn.hutool.core.text.AntPathMatcher;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.utile.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@RequiredArgsConstructor // 使用Lombok生成构造函数，注入final字段
@Component // 将此类标记为Spring组件，使其成为容器中的Bean
@EnableConfigurationProperties(AuthProperties.class) // 启用AuthProperties类的配置属性支持
/**
 * AuthGlobalFilter类
 * 实现GlobalFilter接口，提供全局过滤功能
 * 实现Ordered接口，定义过滤器的执行顺序
 */
public class AuthGlobalFiter implements GlobalFilter , Ordered {
    // 认证属性配置对象，用于存储认证相关的配置信息
    private final AuthProperties authProperties;
    // 路径匹配器，用于实现URL路径模式匹配，支持通配符等
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    // JWT工具类，用于处理JWT令牌的生成、解析和验证等操作
    private final JwtTool jwtTool;

    /**
     * 重写filter方法，实现网关的过滤功能
     * @param exchange 当前的服务网络交换对象，包含请求和响应信息
     * @param chain 网关过滤器链，用于传递请求到下一个过滤器
     * @return Mono<Void> 表示异步操作的完成
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取当前请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 判断请求路径是否在排除列表中，如果是则直接放行
        if (isExclude(request.getPath().toString())) {
            return chain.filter(exchange);
        }
        // 从请求头中获取authorization字段的token值
        String token = request.getHeaders().getFirst("authorization");
        try {
            // 使用JWT工具类解析token，获取用户ID
            Long userId = jwtTool.parseToken(token);
            // 打印用户ID（仅用于调试）
            System.out.println("userId: " + userId);
            // 将用户ID添加到请求头中，供后续的服务调用使用
            exchange.mutate().request(builder ->
            {
                builder.header("user-info", userId.toString());
            }).build();
        } catch (Exception e) {
            // 如果token解析失败，设置响应状态为未授权
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            // 返回响应并结束请求处理
            return response.setComplete();
        }
        // token验证通过，继续执行过滤器链
        return chain.filter(exchange);
    }

    /**
     * 检查给定路径是否在排除路径列表中
     * @param path 需要检查的路径
     * @return 如果路径在排除列表中返回true，否则返回false
     */
    private boolean isExclude(String path) {
        // 遍历配置中的所有排除路径
        for (String excludePath : authProperties.getExcludePaths()) {
            // 使用Ant风格的路径匹配规则检查当前路径是否匹配排除路径
            if (antPathMatcher.match(excludePath, path)) {
                // 如果匹配，返回true表示该路径在排除范围内
                return true;
            }
        }
        // 遍历完所有排除路径都没有匹配，返回false
        return false;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
